home *** CD-ROM | disk | FTP | other *** search
/ Acorn User: China / Acorn User China CD-ROM (UK) (Disc A) / Acorn User China CD-ROM (UK) (Disc A).bin / DEMON / RISCOS2 / ARCKA9Q1.ARC / c / NR4SUBR < prev    next >
Encoding:
Text File  |  1992-03-05  |  10.8 KB  |  369 lines

  1. /*
  2.  * nr4subr.c:  subroutines for net/rom transport layer.
  3.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  4.  * non-commercial distribution only.
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <time.h>
  10. #include <ctype.h>
  11. #include "global.h"
  12. #include "mbuf.h"
  13. #include "timer.h"
  14. #include "ax25.h"
  15. #include "netrom.h"
  16. #include "nr4.h"
  17. #include "lapb.h"
  18.  
  19.  
  20. /* Convert a net/rom transport header to host format structure.
  21.  * Return -1 if error, 0 if OK.
  22.  */
  23.  
  24. int ntohnr4(register struct nr4hdr *hdr, struct mbuf **bpp)
  25. {
  26.         char axbuf[AXALEN] ;
  27.         char tbuf[NR4MINHDR] ;
  28.  
  29.         if (pullup(bpp, tbuf, NR4MINHDR) < NR4MINHDR)
  30.                 return -1 ;
  31.  
  32.         hdr->opcode = tbuf[4] ;
  33.  
  34.         switch (tbuf[4] & NR4OPCODE) {
  35.  
  36.                 case NR4OPPID:                  /* protocol ID extension */
  37.                         hdr->u.pid.family = tbuf[0] ;
  38.                         hdr->u.pid.proto = tbuf[1] ;
  39.                         break ;
  40.  
  41.                 case NR4OPCONRQ:                /* connect request */
  42.                         hdr->u.conreq.myindex = tbuf[0] ;
  43.                         hdr->u.conreq.myid = tbuf[1] ;
  44.                         if (pullup(bpp,&(hdr->u.conreq.window), 1) < 1)
  45.                                 return -1 ;
  46.                         if (pullup(bpp,axbuf,AXALEN) < AXALEN)
  47.                                 return -1 ;
  48.                         (void)getaxaddr(&hdr->u.conreq.user,axbuf) ;
  49.                         if (pullup(bpp,axbuf,AXALEN) < AXALEN)
  50.                                 return -1 ;
  51.                         getaxaddr(&hdr->u.conreq.node,axbuf) ;
  52.                         break ;
  53.  
  54.                 case NR4OPCONAK:                /* connect acknowledge */
  55.                         hdr->yourindex = tbuf[0] ;
  56.                         hdr->yourid = tbuf[1] ;
  57.                         hdr->u.conack.myindex = tbuf[2] ;
  58.                         hdr->u.conack.myid = tbuf[3] ;
  59.                         if (pullup(bpp,&(hdr->u.conack.window), 1) < 1)
  60.                                 return -1 ;
  61.                         break ;
  62.  
  63.                 case NR4OPDISRQ:                /* disconnect request */
  64.                         hdr->yourindex = tbuf[0] ;
  65.                         hdr->yourid = tbuf[1] ;
  66.                         break ;
  67.  
  68.                 case NR4OPDISAK:                /* disconnect acknowledge */
  69.                         hdr->yourindex = tbuf[0] ;
  70.                         hdr->yourid = tbuf[1] ;
  71.                         break ;
  72.  
  73.                 case NR4OPINFO:                 /* information frame */
  74.                         hdr->yourindex = tbuf[0] ;
  75.                         hdr->yourid = tbuf[1] ;
  76.                         hdr->u.info.txseq = tbuf[2] ;
  77.                         hdr->u.info.rxseq = tbuf[3] ;
  78.                         break ;
  79.  
  80.                 case NR4OPACK:                  /* information acknowledge */
  81.                         hdr->yourindex = tbuf[0] ;
  82.                         hdr->yourid = tbuf[1] ;
  83.                         hdr->u.ack.rxseq = tbuf[3] ;
  84.                         break ;
  85.  
  86.                 default:                                /* what kind of frame is this? */
  87.                         return -1 ;
  88.         }
  89.  
  90.         return 0 ;
  91. }
  92.  
  93.  
  94. struct mbuf *htonnr4(register struct nr4hdr *hdr)
  95. {
  96.         static unsigned char hlen[NR4NUMOPS] = {5,20,6,5,5,5,5} ;
  97.         struct mbuf *rbuf ;
  98.         register char *cp ;
  99.         unsigned char opcode ;
  100.  
  101.         opcode = hdr->opcode & NR4OPCODE ;
  102.  
  103.         if (opcode >= NR4NUMOPS)
  104.                 return NULLBUF ;
  105.  
  106.         if (hdr == (struct nr4hdr *)NULL)
  107.                 return NULLBUF ;
  108.  
  109.         if ((rbuf = alloc_mbuf(hlen[opcode])) == NULLBUF)
  110.                 return NULLBUF ;
  111.  
  112.         rbuf->cnt = hlen[opcode] ;
  113.         cp = rbuf->data ;
  114.  
  115.         cp[4] = hdr->opcode ;
  116.         
  117.         switch (opcode) {
  118.         
  119.                 case NR4OPPID:
  120.                         *cp++ = hdr->u.pid.family ;
  121.                         *cp = hdr->u.pid.proto ;
  122.                         break ;
  123.  
  124.                 case NR4OPCONRQ:
  125.                         *cp++ = hdr->u.conreq.myindex ;
  126.                         *cp++ = hdr->u.conreq.myid ;
  127.                         cp += 3 ;                                               /* skip to sixth byte */
  128.                         *cp++ = hdr->u.conreq.window ;
  129.                         cp = putaxaddr(cp, &hdr->u.conreq.user) ;
  130.                         (void) putaxaddr(cp, &hdr->u.conreq.node) ;
  131.                         break ;
  132.  
  133.                 case NR4OPCONAK:
  134.                         *cp++ = hdr->yourindex ;
  135.                         *cp++ = hdr->yourid ;
  136.                         *cp++ = hdr->u.conack.myindex ;
  137.                         *cp++ = hdr->u.conack.myid ;
  138.                         cp++ ;                                                  /* already loaded pid */
  139.                         *cp = hdr->u.conack.window ;
  140.                         break ;
  141.  
  142.                 case NR4OPDISRQ:
  143.                         *cp++ = hdr->yourindex ;
  144.                         *cp = hdr->yourid ;
  145.                         break ;
  146.  
  147.                 case NR4OPDISAK:
  148.                         *cp++ = hdr->yourindex ;
  149.                         *cp = hdr->yourid ;
  150.                         break ;
  151.  
  152.                 case NR4OPINFO:
  153.                         *cp++ = hdr->yourindex ;
  154.                         *cp++ = hdr->yourid ;
  155.                         *cp++ = hdr->u.info.txseq ;
  156.                         *cp = hdr->u.info.rxseq ;
  157.                         break ;
  158.  
  159.                 case NR4OPACK:
  160.                         *cp++ = hdr->yourindex ;
  161.                         *cp++ = hdr->yourid ;
  162.                         *++cp = hdr->u.ack.rxseq ;      /* skip third byte (tricky yuck) */
  163.                         break ;
  164.  
  165.         }
  166.  
  167.         return rbuf ;
  168. }
  169.  
  170.  
  171. /* Get a free circuit table entry, and allocate a circuit descriptor.
  172.  * Initialize control block circuit number and ID fields.
  173.  * Return a pointer to the circuit control block if successful,
  174.  * NULLNR4CB if not.
  175.  */
  176.  
  177. struct nr4cb *new_n4circ(void)
  178. {
  179.         int i ;
  180.         struct nr4cb *cb ;
  181.  
  182.         for (i = 0 ; i <  NR4MAXCIRC ; i++)             /* find a free circuit */
  183.                 if (Nr4circuits[i].ccb == NULLNR4CB)
  184.                         break ;
  185.  
  186.         if (i == NR4MAXCIRC)    /* no more circuits */
  187.                 return NULLNR4CB ;
  188.  
  189.         if ((cb = Nr4circuits[i].ccb =
  190.                  (struct nr4cb *)calloc(1,sizeof(struct nr4cb))) == NULLNR4CB)
  191.                 return NULLNR4CB ;
  192.         else {
  193.                 cb->mynum = i ;
  194.                 cb->myid = Nr4circuits[i].cid ;
  195.                 return cb ;
  196.         }
  197. }
  198.  
  199.  
  200. /* Set the window size for a circuit and allocate the buffers for
  201.  * the transmit and receive windows.  Set the control block window
  202.  * parameter.  Return 0 if successful, -1 if not.
  203.  */
  204.  
  205. int init_nr4window(struct nr4cb *cb, unsigned int window)
  206. {
  207.         
  208.         if (window == 0 || window > NR4MAXWIN) /* reject silly window sizes */
  209.                 return -1 ;
  210.                 
  211.         if ((cb->txbufs =
  212.                  (struct nr4txbuf *)calloc(window,sizeof(struct nr4txbuf)))
  213.                  == (struct nr4txbuf *)0)
  214.                 return -1 ;
  215.  
  216.         if ((cb->rxbufs =
  217.                  (struct nr4rxbuf *)calloc(window,sizeof(struct nr4rxbuf)))
  218.                  == (struct nr4rxbuf *)0) {
  219.                 free(cb->txbufs) ;
  220.                 cb->txbufs = (struct nr4txbuf *)0 ;
  221.                 return -1 ;
  222.         }
  223.  
  224.         cb->window = window ;
  225.         
  226.         return 0 ;
  227. }
  228.  
  229.  
  230. /* Free a circuit.  Deallocate the control block and buffers, and
  231.  * increment the circuit ID.  No return value.
  232.  */
  233.  
  234. void free_n4circ(struct nr4cb *cb)
  235. {
  236.         unsigned circ ;
  237.  
  238.         if (cb == NULLNR4CB)
  239.                 return ;
  240.  
  241.         circ = cb->mynum ;
  242.         
  243.         if (cb->txbufs != (struct nr4txbuf *)0)
  244.                 free(cb->txbufs) ;
  245.  
  246.         if (cb->rxbufs != (struct nr4rxbuf *)0)
  247.                 free(cb->rxbufs) ;
  248.  
  249.         /* Better be safe than sorry: */
  250.  
  251.         free_q(&cb->txq) ;
  252.         free_q(&cb->rxq) ;
  253.         
  254.         free(cb) ;
  255.  
  256.         if (circ > NR4MAXCIRC)          /* Shouldn't happen. */
  257.                 return ;
  258.                 
  259.         Nr4circuits[circ].ccb = NULLNR4CB ;
  260.  
  261.         Nr4circuits[circ].cid++ ;
  262. }
  263.  
  264. /* See if any open circuit matches the given parameters.  This is used
  265.  * to prevent opening multiple circuits on a duplicate connect request.
  266.  * Returns the control block address if a match is found, or NULLNR4CB
  267.  * otherwise.
  268.  */
  269.  
  270. struct nr4cb *match_n4circ(int index, int id, struct ax25_addr *user,
  271.                            struct ax25_addr *node)
  272. {
  273.         int i ;
  274.         struct nr4cb *cb ;
  275.  
  276.         for (i = 0 ; i < NR4MAXCIRC ; i++) {
  277.                 if ((cb = Nr4circuits[i].ccb) == NULLNR4CB)
  278.                         continue ;              /* not an open circuit */
  279.                 if (cb->yournum == index && cb->yourid == id
  280.                         && addreq(&cb->user,user) && addreq(&cb->node,node))
  281.                         return cb ;
  282.         }
  283.  
  284.         /* if we get to here, we didn't find a match */
  285.  
  286.         return NULLNR4CB ;
  287. }
  288.  
  289. /* Validate the index and id of a local circuit, returning the control
  290.  * block if it is valid, or NULLNR4CB if it is not.
  291.  */
  292.  
  293. struct nr4cb *get_n4circ(int index, int id)
  294. {
  295.         struct nr4cb *cb ;
  296.  
  297.         if (index >= NR4MAXCIRC)
  298.                 return NULLNR4CB ;
  299.  
  300.         if ((cb = Nr4circuits[index].ccb) == NULLNR4CB)
  301.                 return NULLNR4CB ;
  302.  
  303.         if (cb->myid == id)
  304.                 return cb ;
  305.         else
  306.                 return NULLNR4CB ;
  307. }
  308.  
  309. /* Return 1 if b is "between" (modulo the size of an unsigned char)
  310.  * a and c, 0 otherwise.
  311.  */
  312.  
  313. int nr4between(unsigned a, unsigned b, unsigned c)
  314. {
  315.         if ((a <= b && b < c) || (c < a && a <= b) || (b < c && c < a))
  316.                 return 1 ;
  317.         else
  318.                 return 0 ;
  319. }
  320.  
  321. /* Set up default timer values, etc., in newly connected control block.
  322.  */
  323.  
  324. void nr4defaults(struct nr4cb *cb)
  325. {
  326.         int i ;
  327.         struct timer *t ;
  328.  
  329.         if (cb == NULLNR4CB)
  330.                 return ;
  331.  
  332.         /* Set up the ACK and CHOKE timers */
  333.         
  334.         cb->tack.start = Nr4acktime / MSPTICK ;
  335.         cb->tack.func = nr4ackit ;
  336.         cb->tack.arg = (char *)cb ;
  337.  
  338.         cb->tchoke.start = Nr4choketime / MSPTICK ;
  339.         cb->tchoke.func = nr4unchoke ;
  340.         cb->tchoke.arg = (char *)cb ;
  341.  
  342.         cb->rxpastwin = cb->window ;
  343.  
  344.         /* Don't actually set the timers, since this is done */
  345.         /* in nr4sbuf */
  346.         
  347.         for (i = 0 ; i < cb->window ; i++) {
  348.                 t = &cb->txbufs[i].tretry ;
  349.                 t->func = nr4txtimeout ;
  350.                 t->arg = (char *)cb ;
  351.         }
  352. }
  353.  
  354. /* See if this control block address is valid */
  355.  
  356. int nr4valcb(struct nr4cb *cb)
  357. {
  358.         int i ;
  359.  
  360.         if (cb == NULLNR4CB)
  361.                 return 0 ;
  362.                 
  363.         for (i = 0 ; i < NR4MAXCIRC ; i++)
  364.                 if (Nr4circuits[i].ccb == cb)
  365.                         return 1 ;
  366.  
  367.         return 0 ;
  368. }
  369.